import sys
import os
import subprocess
import configparser
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
                             QHBoxLayout, QGridLayout, QGroupBox, QLabel,
                             QLineEdit, QPushButton, QComboBox, QRadioButton,
                             QButtonGroup, QTextEdit, QStatusBar, QFileDialog,
                             QMessageBox, QProgressBar, QFrame)
from PyQt5.QtCore import QProcess, QTimer, pyqtSignal, Qt
from PyQt5.QtGui import QFont, QTextCursor


class ConfigManager:
    """配置文件管理器"""

    def __init__(self):
        self.config_path = ""
        self.config = configparser.ConfigParser()

    def load_config(self, config_path):
        """加载配置文件"""
        self.config_path = config_path
        if os.path.exists(config_path):
            self.config.read(config_path, encoding='utf-8')
            return True
        return False

    def save_config(self):
        """保存配置文件"""
        if self.config_path:
            with open(self.config_path, 'w', encoding='utf-8') as f:
                self.config.write(f)
            return True
        return False

    def get_openai_config(self):
        """获取OpenAI配置"""
        try:
            return {
                'api_key': self.config.get('OpenAI', 'api_key', fallback=''),
                'base_url': self.config.get('OpenAI', 'base_url', fallback=''),
                'model_name': self.config.get('OpenAI', 'model_name', fallback='')
            }
        except:
            return {'api_key': '', 'base_url': '', 'model_name': ''}

    def set_openai_config(self, api_key, base_url, model_name):
        """设置OpenAI配置"""
        if not self.config.has_section('OpenAI'):
            self.config.add_section('OpenAI')
        self.config.set('OpenAI', 'api_key', api_key)
        self.config.set('OpenAI', 'base_url', base_url)
        self.config.set('OpenAI', 'model_name', model_name)

    def get_youdao_config(self):
        """获取有道配置"""
        try:
            return {
                'access_key_id': self.config.get('YoudaoCloud', 'access_key_id', fallback=''),
                'access_key_secret': self.config.get('YoudaoCloud', 'access_key_secret', fallback='')
            }
        except:
            return {'access_key_id': '', 'access_key_secret': ''}

    def set_youdao_config(self, access_key_id, access_key_secret):
        """设置有道配置"""
        if not self.config.has_section('YoudaoCloud'):
            self.config.add_section('YoudaoCloud')
        self.config.set('YoudaoCloud', 'access_key_id', access_key_id)
        self.config.set('YoudaoCloud', 'access_key_secret', access_key_secret)


class JupyterTranslatorGUI(QMainWindow):
    """Jupyter Notebook翻译工具GUI主窗口"""

    def __init__(self):
        super().__init__()
        self.config_manager = ConfigManager()
        self.process = None
        self.init_ui()
        self.load_default_config()

    def init_ui(self):
        """初始化用户界面"""
        self.setWindowTitle("Jupyter Notebook 翻译工具")
        self.setGeometry(100, 100, 900, 700)

        # 创建中央控件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)

        # 主布局
        main_layout = QVBoxLayout(central_widget)
        main_layout.setSpacing(10)
        main_layout.setContentsMargins(10, 10, 10, 10)

        # 创建各个区域
        self.create_config_section(main_layout)
        self.create_file_section(main_layout)
        self.create_control_section(main_layout)

        # 创建状态栏
        self.status_bar = QStatusBar()
        self.setStatusBar(self.status_bar)
        self.status_bar.showMessage("就绪")

        # 应用样式
        self.apply_styles()

    def create_config_section(self, parent_layout):
        """创建配置管理区域"""
        config_group = QGroupBox("配置管理")
        config_layout = QVBoxLayout(config_group)

        # 配置文件选择
        config_file_layout = QHBoxLayout()
        config_file_layout.addWidget(QLabel("配置文件路径:"))

        self.config_path_edit = QLineEdit()
        self.config_path_edit.setReadOnly(True)
        config_file_layout.addWidget(self.config_path_edit)

        self.browse_config_btn = QPushButton("浏览...")
        self.browse_config_btn.clicked.connect(self.browse_config_file)
        config_file_layout.addWidget(self.browse_config_btn)

        config_layout.addLayout(config_file_layout)

        # 翻译引擎选择
        engine_layout = QHBoxLayout()
        engine_layout.addWidget(QLabel("翻译引擎:"))

        self.engine_group = QButtonGroup()
        self.youdao_radio = QRadioButton("有道智云")
        self.ai_radio = QRadioButton("OpenAI")
        self.youdao_radio.setChecked(True)

        self.engine_group.addButton(self.youdao_radio, 0)
        self.engine_group.addButton(self.ai_radio, 1)
        self.engine_group.buttonClicked.connect(self.on_engine_changed)

        engine_layout.addWidget(self.youdao_radio)
        engine_layout.addWidget(self.ai_radio)
        engine_layout.addStretch()

        config_layout.addLayout(engine_layout)

        # OpenAI配置区域
        self.openai_group = QGroupBox("OpenAI 配置")
        openai_layout = QGridLayout(self.openai_group)

        openai_layout.addWidget(QLabel("API Key:"), 0, 0)
        self.openai_api_key_edit = QLineEdit()
        self.openai_api_key_edit.setEchoMode(QLineEdit.Password)
        openai_layout.addWidget(self.openai_api_key_edit, 0, 1)

        openai_layout.addWidget(QLabel("Base URL:"), 1, 0)
        self.openai_base_url_edit = QLineEdit()
        openai_layout.addWidget(self.openai_base_url_edit, 1, 1)

        openai_layout.addWidget(QLabel("Model Name:"), 2, 0)
        self.openai_model_edit = QLineEdit()
        openai_layout.addWidget(self.openai_model_edit, 2, 1)

        config_layout.addWidget(self.openai_group)

        # 有道配置区域
        self.youdao_group = QGroupBox("有道智云配置")
        youdao_layout = QGridLayout(self.youdao_group)

        youdao_layout.addWidget(QLabel("Access Key ID:"), 0, 0)
        self.youdao_access_key_edit = QLineEdit()
        self.youdao_access_key_edit.setEchoMode(QLineEdit.Password)
        youdao_layout.addWidget(self.youdao_access_key_edit, 0, 1)

        youdao_layout.addWidget(QLabel("Access Key Secret:"), 1, 0)
        self.youdao_secret_key_edit = QLineEdit()
        self.youdao_secret_key_edit.setEchoMode(QLineEdit.Password)
        youdao_layout.addWidget(self.youdao_secret_key_edit, 1, 1)

        config_layout.addWidget(self.youdao_group)

        # 保存配置按钮
        save_config_btn = QPushButton("保存配置")
        save_config_btn.clicked.connect(self.save_config)
        config_layout.addWidget(save_config_btn)

        parent_layout.addWidget(config_group)

        # 初始化显示状态
        self.update_config_visibility()

    def create_file_section(self, parent_layout):
        """创建文件操作区域"""
        file_group = QGroupBox("文件操作")
        file_layout = QGridLayout(file_group)

        file_layout.addWidget(QLabel("输入文件:"), 0, 0)
        self.input_file_edit = QLineEdit()
        self.input_file_edit.setReadOnly(True)
        file_layout.addWidget(self.input_file_edit, 0, 1)

        self.browse_input_btn = QPushButton("选择 .ipynb 文件...")
        self.browse_input_btn.clicked.connect(self.browse_input_file)
        file_layout.addWidget(self.browse_input_btn, 0, 2)

        file_layout.addWidget(QLabel("输出文件:"), 1, 0)
        self.output_file_edit = QLineEdit()
        self.output_file_edit.setReadOnly(True)
        file_layout.addWidget(self.output_file_edit, 1, 1)

        self.browse_output_btn = QPushButton("另存为...")
        self.browse_output_btn.clicked.connect(self.browse_output_file)
        file_layout.addWidget(self.browse_output_btn, 1, 2)

        parent_layout.addWidget(file_group)

    def create_control_section(self, parent_layout):
        """创建翻译控制与日志区域"""
        control_group = QGroupBox("翻译控制与日志")
        control_layout = QVBoxLayout(control_group)

        # 控制按钮
        button_layout = QHBoxLayout()
        self.translate_btn = QPushButton("开始翻译")
        self.translate_btn.clicked.connect(self.start_translation)
        self.translate_btn.setStyleSheet("QPushButton { background-color: #4CAF50; color: white; font-weight: bold; }")

        self.clear_log_btn = QPushButton("清空日志")
        self.clear_log_btn.clicked.connect(self.clear_log)

        button_layout.addWidget(self.translate_btn)
        button_layout.addWidget(self.clear_log_btn)
        button_layout.addStretch()

        control_layout.addLayout(button_layout)

        # 进度条
        self.progress_bar = QProgressBar()
        self.progress_bar.setVisible(False)
        control_layout.addWidget(self.progress_bar)

        # 日志输出区域
        control_layout.addWidget(QLabel("实时日志:"))
        self.log_text = QTextEdit()
        self.log_text.setReadOnly(True)
        self.log_text.setFont(QFont("Consolas", 9))
        self.log_text.setMaximumHeight(300)
        control_layout.addWidget(self.log_text)

        parent_layout.addWidget(control_group)

    def apply_styles(self):
        """应用样式"""
        self.setStyleSheet("""
            QGroupBox {
                font-weight: bold;
                border: 2px solid #cccccc;
                border-radius: 5px;
                margin-top: 1ex;
                padding-top: 10px;
            }
            QGroupBox::title {
                subcontrol-origin: margin;
                left: 10px;
                padding: 0 5px 0 5px;
            }
            QPushButton {
                padding: 8px 16px;
                border: 1px solid #ccc;
                border-radius: 4px;
                background-color: #f8f9fa;
            }
            QPushButton:hover {
                background-color: #e9ecef;
            }
            QLineEdit {
                padding: 6px;
                border: 1px solid #ddd;
                border-radius: 4px;
            }
            QTextEdit {
                border: 1px solid #ddd;
                border-radius: 4px;
            }
        """)

    def load_default_config(self):
        """加载默认配置文件"""
        script_dir = os.path.dirname(os.path.abspath(__file__))
        default_config_path = os.path.join(script_dir, 'config.ini')
        self.config_path_edit.setText(default_config_path)
        self.load_config_from_file(default_config_path)

    def browse_config_file(self):
        """浏览配置文件"""
        file_path, _ = QFileDialog.getOpenFileName(
            self, "选择配置文件", "", "INI 文件 (*.ini);;所有文件 (*)"
        )
        if file_path:
            self.config_path_edit.setText(file_path)
            self.load_config_from_file(file_path)

    def load_config_from_file(self, file_path):
        """从文件加载配置"""
        if self.config_manager.load_config(file_path):
            # 加载OpenAI配置
            openai_config = self.config_manager.get_openai_config()
            self.openai_api_key_edit.setText(openai_config['api_key'])
            self.openai_base_url_edit.setText(openai_config['base_url'])
            self.openai_model_edit.setText(openai_config['model_name'])

            # 加载有道配置
            youdao_config = self.config_manager.get_youdao_config()
            self.youdao_access_key_edit.setText(youdao_config['access_key_id'])
            self.youdao_secret_key_edit.setText(youdao_config['access_key_secret'])

            self.log_message(f"配置文件加载成功: {file_path}")
            self.status_bar.showMessage("配置已加载")
        else:
            self.log_message(f"配置文件不存在或格式错误: {file_path}")
            self.status_bar.showMessage("配置加载失败")

    def save_config(self):
        """保存配置"""
        if not self.config_path_edit.text():
            QMessageBox.warning(self, "警告", "请先选择配置文件路径")
            return

        # 设置配置值
        self.config_manager.set_openai_config(
            self.openai_api_key_edit.text(),
            self.openai_base_url_edit.text(),
            self.openai_model_edit.text()
        )
        self.config_manager.set_youdao_config(
            self.youdao_access_key_edit.text(),
            self.youdao_secret_key_edit.text()
        )

        if self.config_manager.save_config():
            self.log_message("配置保存成功")
            self.status_bar.showMessage("配置已保存")
            QMessageBox.information(self, "成功", "配置已保存")
        else:
            self.log_message("配置保存失败")
            self.status_bar.showMessage("配置保存失败")
            QMessageBox.warning(self, "错误", "配置保存失败")

    def on_engine_changed(self):
        """翻译引擎改变时的处理"""
        self.update_config_visibility()

    def update_config_visibility(self):
        """更新配置区域的显示状态"""
        if self.youdao_radio.isChecked():
            self.openai_group.setVisible(False)
            self.youdao_group.setVisible(True)
        else:
            self.openai_group.setVisible(True)
            self.youdao_group.setVisible(False)

    def browse_input_file(self):
        """浏览输入文件"""
        file_path, _ = QFileDialog.getOpenFileName(
            self, "选择 Jupyter Notebook 文件", "", "Jupyter Notebook (*.ipynb)"
        )
        if file_path:
            self.input_file_edit.setText(file_path)
            # 自动生成输出文件名
            output_path = os.path.splitext(file_path)[0] + '_zh.ipynb'
            self.output_file_edit.setText(output_path)

    def browse_output_file(self):
        """浏览输出文件"""
        if not self.input_file_edit.text():
            QMessageBox.warning(self, "警告", "请先选择输入文件")
            return

        default_path = self.output_file_edit.text() or self.input_file_edit.text()
        file_path, _ = QFileDialog.getSaveFileName(
            self, "选择输出文件", default_path, "Jupyter Notebook (*.ipynb)"
        )
        if file_path:
            self.output_file_edit.setText(file_path)

    def validate_inputs(self):
        """验证输入"""
        if not self.input_file_edit.text():
            QMessageBox.warning(self, "警告", "请选择输入文件")
            return False

        if not os.path.exists(self.input_file_edit.text()):
            QMessageBox.warning(self, "警告", "输入文件不存在")
            return False

        if not self.config_path_edit.text():
            QMessageBox.warning(self, "警告", "请选择配置文件")
            return False

        # 验证对应引擎的配置
        if self.youdao_radio.isChecked():
            if not self.youdao_access_key_edit.text() or not self.youdao_secret_key_edit.text():
                QMessageBox.warning(self, "警告", "请配置有道智云的 Access Key ID 和 Secret")
                return False
        else:
            if not self.openai_api_key_edit.text():
                QMessageBox.warning(self, "警告", "请配置 OpenAI 的 API Key")
                return False

        return True

    def start_translation(self):
        """开始翻译"""
        if not self.validate_inputs():
            return

        # 先保存当前配置
        self.save_config()

        # 获取翻译引擎
        engine = "youdao" if self.youdao_radio.isChecked() else "ai"

        # 构建命令
        cmd = [
            sys.executable, "main.py",
            "-e", engine,
            self.input_file_edit.text()
        ]

        # 启动进程
        self.process = QProcess(self)
        self.process.readyReadStandardOutput.connect(self.read_output)
        self.process.readyReadStandardError.connect(self.read_error)
        self.process.finished.connect(self.translation_finished)
        self.process.errorOccurred.connect(self.translation_error)

        # 设置工作目录
        script_dir = os.path.dirname(os.path.abspath(__file__))
        self.process.setWorkingDirectory(script_dir)

        # 禁用控件
        self.translate_btn.setText("停止翻译")
        self.translate_btn.clicked.disconnect()
        self.translate_btn.clicked.connect(self.stop_translation)
        self.translate_btn.setStyleSheet("QPushButton { background-color: #f44336; color: white; font-weight: bold; }")
        self.progress_bar.setVisible(True)
        self.progress_bar.setRange(0, 0)  # 不确定进度

        # 禁用配置和文件操作控件
        self.set_controls_enabled(False)

        # 清空日志
        self.log_text.clear()

        # 开始翻译
        self.log_message(f"开始翻译，使用引擎: {engine}")
        self.log_message(f"命令: {' '.join(cmd)}")
        self.status_bar.showMessage("正在翻译...")

        try:
            self.process.start(cmd[0], cmd[1:])
        except Exception as e:
            self.log_message(f"启动翻译进程失败: {str(e)}")
            self.translation_finished(1, QProcess.CrashExit)

    def stop_translation(self):
        """停止翻译"""
        if self.process and self.process.state() == QProcess.Running:
            self.process.kill()
            self.log_message("翻译已停止")
            self.translation_finished(0, QProcess.CrashExit)

    def read_output(self):
        """读取标准输出"""
        if self.process:
            data = self.process.readAllStandardOutput()
            text = bytes(data).decode('utf-8', errors='ignore')
            self.log_message(text.strip())

    def read_error(self):
        """读取标准错误"""
        if self.process:
            data = self.process.readAllStandardError()
            text = bytes(data).decode('utf-8', errors='ignore')
            self.log_message(f"错误: {text.strip()}")

    def translation_finished(self, exit_code, exit_status):
        """翻译完成"""
        # 恢复控件
        self.translate_btn.setText("开始翻译")
        self.translate_btn.clicked.disconnect()
        self.translate_btn.clicked.connect(self.start_translation)
        self.translate_btn.setStyleSheet("QPushButton { background-color: #4CAF50; color: white; font-weight: bold; }")
        self.progress_bar.setVisible(False)

        # 启用配置和文件操作控件
        self.set_controls_enabled(True)

        if exit_code == 0:
            self.log_message("翻译完成！")
            self.status_bar.showMessage("翻译完成")

            # 检查输出文件是否存在
            if self.output_file_edit.text() and os.path.exists(self.output_file_edit.text()):
                QMessageBox.information(self, "成功", f"翻译完成！\n输出文件已保存到:\n{self.output_file_edit.text()}")
            else:
                QMessageBox.information(self, "成功", "翻译完成！")
        else:
            self.log_message(f"翻译失败，退出码: {exit_code}")
            self.status_bar.showMessage("翻译失败")
            QMessageBox.warning(self, "错误", "翻译过程中发生错误，请查看日志了解详情")

    def translation_error(self, error):
        """翻译错误"""
        self.log_message(f"进程错误: {error}")
        self.translation_finished(1, QProcess.CrashExit)

    def set_controls_enabled(self, enabled):
        """设置控件启用状态"""
        # 配置区域
        self.browse_config_btn.setEnabled(enabled)
        self.youdao_radio.setEnabled(enabled)
        self.ai_radio.setEnabled(enabled)
        self.openai_api_key_edit.setEnabled(enabled)
        self.openai_base_url_edit.setEnabled(enabled)
        self.openai_model_edit.setEnabled(enabled)
        self.youdao_access_key_edit.setEnabled(enabled)
        self.youdao_secret_key_edit.setEnabled(enabled)

        # 文件操作区域
        self.browse_input_btn.setEnabled(enabled)
        self.browse_output_btn.setEnabled(enabled)

    def clear_log(self):
        """清空日志"""
        self.log_text.clear()

    def log_message(self, message):
        """添加日志消息"""
        self.log_text.append(message)
        # 滚动到底部
        cursor = self.log_text.textCursor()
        cursor.movePosition(QTextCursor.End)
        self.log_text.setTextCursor(cursor)
        # 确保UI更新
        QApplication.processEvents()


def main():
    """主函数"""
    app = QApplication(sys.argv)
    app.setApplicationName("Jupyter Notebook 翻译工具")
    app.setApplicationVersion("1.0")

    window = JupyterTranslatorGUI()
    window.show()

    sys.exit(app.exec_())


if __name__ == "__main__":
    main()